/*
 * GuiDesktop.java
 *
 * Created on 15 settembre 2008, 16.57
 */

package gui;

import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import core.*;
import utility.*;

/**
 *
 * @author  dario
 */
public class GuiDesktop extends javax.swing.JFrame implements ActionListener{

    /** Creates new form GuiDesktop */
    public GuiDesktop() {
        initComponents();
        openMenu.addActionListener(this);
        saveMenu.addActionListener(this);
        exitMenu.addActionListener(this);
        startButton.addActionListener(this);
        aboutMenu.addActionListener(this);
        fc.setCurrentDirectory(new File(basePath));
        _waitingFrame = new WaitingDialog(this);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        fc = new javax.swing.JFileChooser();
        aboutDialog = new javax.swing.JFrame();
        jPanel1 = new javax.swing.JPanel();
        jTextArea1 = new javax.swing.JTextArea();
        jLabel3 = new javax.swing.JLabel();
        outputPanel = new javax.swing.JScrollPane();
        outputLabel = new javax.swing.JLabel();
        inputPanel = new javax.swing.JPanel();
        inputLabel = new javax.swing.JLabel();
        optionsPanel = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        iterationsSpinner = new javax.swing.JSpinner();
        widthComboBox = new javax.swing.JComboBox();
        startButton = new javax.swing.JButton();
        medianCheckBox = new javax.swing.JCheckBox();
        jLabel4 = new javax.swing.JLabel();
        outputWidthComboBox = new javax.swing.JComboBox();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        openMenu = new javax.swing.JMenuItem();
        saveMenu = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JSeparator();
        exitMenu = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        aboutMenu = new javax.swing.JMenuItem();

        aboutDialog.setMinimumSize(new java.awt.Dimension(315, 400));

        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel1.setMinimumSize(new java.awt.Dimension(315, 400));
        jPanel1.setPreferredSize(new java.awt.Dimension(315, 400));
        jPanel1.setRequestFocusEnabled(false);

        jTextArea1.setColumns(20);
        jTextArea1.setEditable(false);
        jTextArea1.setRows(5);
        jTextArea1.setText("JaTeS - JAva TExtures Synthetizer\nversion: 0.1\n\nRealized by\nDi Mauro Daniele\nPortelli Carmelo");
        jTextArea1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        jLabel3.setBackground(new java.awt.Color(0, 128, 255));
        jLabel3.setIcon(new javax.swing.ImageIcon("/home/dario/NetBeansProjects/JaTeS/images/logo.png")); // NOI18N
        jLabel3.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jLabel3.setPreferredSize(new java.awt.Dimension(100, 100));

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGap(24, 24, 24)
                .addComponent(jTextArea1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(27, Short.MAX_VALUE))
            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel1Layout.createSequentialGroup()
                    .addGap(103, 103, 103)
                    .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(110, Short.MAX_VALUE)))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap(195, Short.MAX_VALUE)
                .addComponent(jTextArea1, javax.swing.GroupLayout.PREFERRED_SIZE, 125, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(31, 31, 31))
            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel1Layout.createSequentialGroup()
                    .addGap(25, 25, 25)
                    .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(226, Short.MAX_VALUE)))
        );

        javax.swing.GroupLayout aboutDialogLayout = new javax.swing.GroupLayout(aboutDialog.getContentPane());
        aboutDialog.getContentPane().setLayout(aboutDialogLayout);
        aboutDialogLayout.setHorizontalGroup(
            aboutDialogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        aboutDialogLayout.setVerticalGroup(
            aboutDialogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 353, Short.MAX_VALUE)
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setMinimumSize(new java.awt.Dimension(555, 456));

        outputLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        outputPanel.setViewportView(outputLabel);

        inputPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Input Texture"));
        inputPanel.setPreferredSize(new java.awt.Dimension(200, 200));

        inputLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);

        javax.swing.GroupLayout inputPanelLayout = new javax.swing.GroupLayout(inputPanel);
        inputPanel.setLayout(inputPanelLayout);
        inputPanelLayout.setHorizontalGroup(
            inputPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(inputLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 301, Short.MAX_VALUE)
        );
        inputPanelLayout.setVerticalGroup(
            inputPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(inputLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 171, Short.MAX_VALUE)
        );

        optionsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Controls"));

        jLabel1.setText("Iterations");

        jLabel2.setText("Neighborhood width");

        iterationsSpinner.setModel(new javax.swing.SpinnerNumberModel(1, 1, 10, 1));

        widthComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "8x8", "16x16", "32x32", "64x64" }));
        widthComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                widthComboBoxActionPerformed(evt);
            }
        });

        startButton.setText("Start");

        medianCheckBox.setSelected(true);
        medianCheckBox.setText("Apply Post Elaboration");
        medianCheckBox.setToolTipText("If ticked applies a median filter to the result");
        medianCheckBox.setAlignmentY(0.0F);
        medianCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        medianCheckBox.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        medianCheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        medianCheckBox.setIconTextGap(90);

        jLabel4.setText("Output width");

        outputWidthComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "8x8", "16x16", "32x32", "64x64", "128x128", "256x256" }));
        outputWidthComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                outputWidthComboBoxActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout optionsPanelLayout = new javax.swing.GroupLayout(optionsPanel);
        optionsPanel.setLayout(optionsPanelLayout);
        optionsPanelLayout.setHorizontalGroup(
            optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, optionsPanelLayout.createSequentialGroup()
                .addGroup(optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2)
                    .addComponent(jLabel4))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 82, Short.MAX_VALUE)
                .addGroup(optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(iterationsSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                        .addComponent(widthComboBox, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(outputWidthComboBox, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, optionsPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(startButton))
            .addGroup(optionsPanelLayout.createSequentialGroup()
                .addComponent(medianCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, 289, Short.MAX_VALUE)
                .addContainerGap())
        );
        optionsPanelLayout.setVerticalGroup(
            optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(optionsPanelLayout.createSequentialGroup()
                .addGroup(optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(iterationsSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(widthComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(16, 16, 16)
                .addGroup(optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(outputWidthComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(medianCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 12, Short.MAX_VALUE)
                .addComponent(startButton)
                .addGap(40, 40, 40))
        );

        jMenu1.setText("File");

        openMenu.setText("Open...");
        jMenu1.add(openMenu);

        saveMenu.setText("Save...");
        jMenu1.add(saveMenu);
        jMenu1.add(jSeparator1);

        exitMenu.setText("Exit");
        jMenu1.add(exitMenu);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Help");

        aboutMenu.setText("About");
        jMenu2.add(aboutMenu);

        jMenuBar1.add(jMenu2);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(outputPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 224, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(inputPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 313, Short.MAX_VALUE)
                    .addComponent(optionsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(inputPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(optionsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
            .addComponent(outputPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 452, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void widthComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_widthComboBoxActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_widthComboBoxActionPerformed

private void outputWidthComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_outputWidthComboBoxActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_outputWidthComboBoxActionPerformed
public void actionPerformed(ActionEvent e)
{
    Object src = e.getSource();
    if(src == openMenu)
    {
         
        int returnVal =fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION)
        {
            File file = fc.getSelectedFile();
            try {
                _input_image = ImageIO.read(file);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            if(_input_image != null)
            {
                inputLabel.setIcon(new ImageIcon(_input_image));
                inputLabel.repaint();
                _output_image = null;
                outputLabel.setIcon(null);
                outputLabel.repaint();
            }
            
            
        }
    }
    else if(src == saveMenu)
    {
        int returnVal =fc.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION)
        {
            File file = fc.getSelectedFile();
            try {
                ImageIO.write(_output_image, file.getName().split("\\.")[1], file);
                System.out.println("File scritto correttamente");
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            if(_input_image != null)
            {
                inputLabel.setIcon(new ImageIcon(_input_image));
                inputLabel.repaint();
            }
        }
        
    }
    else if(src == startButton)
    {
        if(_input_image == null)
        {
            JOptionPane.showMessageDialog(this, "Choose an input texture", "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }
        else if(Integer.parseInt(widthComboBox.getSelectedItem().toString().split("x")[0]) >= _input_image.getWidth())
        {
            JOptionPane.showMessageDialog(this, "Neighborhood width >= input texture size.", "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }
        _output_image = null;
        outputLabel.setIcon(null);
        outputLabel.repaint();
        //Avvio il thread che mostra la finestra di attesa...
        _waitingFrame.setMessage("Now synthetizing...");
        Thread t = new Thread(_waitingFrame);
        t.start();
        runSynthetizer(medianCheckBox.isSelected());

        
        
    }
    else if(src == exitMenu)
    {
        System.exit(0);
    }
    else if(src == aboutMenu)
    {
        aboutDialog.setVisible(true);
    }
}
    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new GuiDesktop().setVisible(true);
            }
        });
    }
    
    public void runSynthetizer( boolean postElaboration )
    {
        final boolean post = postElaboration;
        _synthetizeThread = new Thread( new Runnable()
        {
            public void run()
            {
                TextureSynthetizer ts = null;
                int width = 32;
                int height = 32;
                int intorno = Integer.parseInt(widthComboBox.getSelectedItem().toString().split("x")[0]);
                //int intorno = 16;
                int iterations = (Integer)iterationsSpinner.getValue();
        //        int iterations = 5;
                _output_image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

                        /*Inizializzo l'immagine con colori casuali*/
                        int r = 0,
                            g = 0,
                            b = 0;
                        Color auxColor; //Colore casuale creato ad ogni iterazione
                        for(int i=0; i<width; i++)
                            for(int j=0; j<height; j++)
                            {
                                r = (int)(Math.random()*256);
                                g = (int)(Math.random()*256);
                                b = (int)(Math.random()*256);
                                auxColor = new Color(r, r, r);
                                _output_image.setRGB(i, j, auxColor.getRGB());
                            }
                        
                        
                int outputWidth = Integer.parseInt(outputWidthComboBox.getSelectedItem().toString().split("x")[0]);
                ts = new TextureSynthetizer(iterations, intorno, _input_image, Utility.getScaledInstance(_output_image, 32, 32, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR, false)); //Ottengo una immagine iniziale più fedele
                for(int currentWidth=width; currentWidth<=outputWidth; currentWidth*=2)
                {
                    ts.reinitialize(iterations, intorno, _input_image, Utility.getScaledInstance(_output_image, currentWidth, currentWidth, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR, false)); //Ottengo una immagine iniziale più fedele
                    ts.synthetize();
                }



                _output_image = ts.getOutputImage();
                if(post)
                    Utility.medianFilter(_output_image, 3);
                //Fermo il thread della finestra di attesa
                _waitingFrame.setFinished(true);
                //Mostro il risultato nell'apposito pannello
                outputLabel.setIcon(new ImageIcon(_output_image));
                outputLabel.repaint();
            }
        });
        _synthetizeThread.start();
        
    }
    
    public void stopSynthesis()
    {
        try
        {
            _synthetizeThread.stop();
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JFrame aboutDialog;
    private javax.swing.JMenuItem aboutMenu;
    private javax.swing.JMenuItem exitMenu;
    private javax.swing.JFileChooser fc;
    private javax.swing.JLabel inputLabel;
    private javax.swing.JPanel inputPanel;
    private javax.swing.JSpinner iterationsSpinner;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JCheckBox medianCheckBox;
    private javax.swing.JMenuItem openMenu;
    private javax.swing.JPanel optionsPanel;
    private javax.swing.JLabel outputLabel;
    private javax.swing.JScrollPane outputPanel;
    private javax.swing.JComboBox outputWidthComboBox;
    private javax.swing.JMenuItem saveMenu;
    private javax.swing.JButton startButton;
    private javax.swing.JComboBox widthComboBox;
    // End of variables declaration//GEN-END:variables
    private WaitingDialog _waitingFrame;
    private BufferedImage _input_image;
    private BufferedImage _output_image;
    private final String basePath = "/home/dario/NetBeansProjects/JaTeS/images";
    private float percentage = 0.0f;
    private Thread _synthetizeThread;
}


